from tqdm import tqdm


class Network:
    def __init__(self):
        self.layers = []

    def add_layer(self, layer):
        self.layers.append(layer)

    def forward(self, inputs):
        for layer in self.layers:
            inputs = layer.forward(inputs)
        return inputs

    def backward(self, loss_gradient):
        for layer in reversed(self.layers):
            loss_gradient = layer.backward(loss_gradient)

    def train(self, X, y, epochs, learning_rate):
        progress_bar = tqdm(total=len(X) * epochs, desc="Training")
        for epoch in range(epochs):
            for inputs, target in zip(X, y):
                # Forward pass
                output = self.forward(inputs)
                # Compute loss (simple mean squared error)
                loss = ((output - target) ** 2).mean()
                # Backward pass
                loss_gradient = 2 * (output - target) / output.size
                self.backward(loss_gradient)
                # Update weights
                for layer in self.layers:
                    layer.update_weights(learning_rate)
                progress_bar.update(1)

    def predict(self, X):
        predictions = []
        for inputs in X:
            predictions.append(self.forward(inputs))
        return predictions
